package webmarket.common;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;

import webmarket.controller.ControllerBase;

public class MarkerController extends ControllerBase {
	public static enum MarkerTypes {
		BAD_REQUEST, LOGIN, USERS, FORBIDDEN, ERRORS, INTERNAL_ERROR, LOGOUT, CREATE, SELL, NOT_FOUND, SHOP, REGISTER, LOGIN_INVALID, PICTURE
	}

	private MarkerController() {
	}

	private static final Map<MarkerTypes, String> markerNames = new HashMap<MarkerTypes, String>();
	private static final Map<MarkerTypes, Marker> markers = new HashMap<MarkerTypes, Marker>();
	private static final MarkerTypes[] roots = new MarkerTypes[] { MarkerTypes.ERRORS, MarkerTypes.USERS, MarkerTypes.SHOP };
	private static final Map<MarkerTypes, List<MarkerTypes>> markerTree = new HashMap<MarkerTypes, List<MarkerTypes>>();

	static {
		logger.entry();
		getMarkernames().put(MarkerTypes.ERRORS, "Hibák");
		getMarkernames().put(MarkerTypes.BAD_REQUEST, "Hibás lekérés");
		getMarkernames().put(MarkerTypes.INTERNAL_ERROR, "Szerver oldali hiba");
		getMarkernames().put(MarkerTypes.NOT_FOUND, "Nem található");
		getMarkernames().put(MarkerTypes.FORBIDDEN, "Nem engedélyezett");

		getMarkernames().put(MarkerTypes.USERS, "Felhasználó");
		getMarkernames().put(MarkerTypes.LOGIN, "Bejelentkezés");
		getMarkernames().put(MarkerTypes.REGISTER, "Új felhasználó");
		getMarkernames().put(MarkerTypes.LOGIN_INVALID, "Piactér");
		getMarkernames().put(MarkerTypes.LOGOUT, "Kijelentkezés");

		getMarkernames().put(MarkerTypes.SHOP, "Piactér");
		getMarkernames().put(MarkerTypes.CREATE, "Létrehozás");
		getMarkernames().put(MarkerTypes.SELL, "Megvétel");
		getMarkernames().put(MarkerTypes.PICTURE, "Képfeltöltés");

		for (MarkerTypes root : roots) {
			createRoot(root);
		}

		createInheritence(MarkerTypes.BAD_REQUEST, MarkerTypes.ERRORS);
		createInheritence(MarkerTypes.INTERNAL_ERROR, MarkerTypes.ERRORS);
		createInheritence(MarkerTypes.NOT_FOUND, MarkerTypes.ERRORS);
		createInheritence(MarkerTypes.FORBIDDEN, MarkerTypes.ERRORS);

		createInheritence(MarkerTypes.LOGIN, MarkerTypes.USERS);
		createInheritence(MarkerTypes.REGISTER, MarkerTypes.USERS);
		createInheritence(MarkerTypes.LOGIN_INVALID, MarkerTypes.USERS);
		createInheritence(MarkerTypes.LOGOUT, MarkerTypes.USERS);

		createInheritence(MarkerTypes.CREATE, MarkerTypes.SHOP);
		createInheritence(MarkerTypes.SELL, MarkerTypes.SHOP);
		createInheritence(MarkerTypes.PICTURE, MarkerTypes.SHOP);

		logger.exit();
	}

	private static void createRoot(MarkerTypes root) {
		getMarkers().put(root, MarkerManager.getMarker(root.toString()));
	}

	private static void createInheritence(MarkerTypes child, MarkerTypes parent) {
		getMarkers().put(child, MarkerManager.getMarker(child.toString(), parent.toString()));
		if (!markerTree.containsKey(parent)) {
			markerTree.put(parent, new LinkedList<MarkerTypes>());
		}
		markerTree.get(parent).add(child);
	}

	public static List<Marker> getAllLeafs(MarkerTypes marker) {
		logger.entry(marker);
		List<MarkerTypes> children = markerTree.get(marker);
		List<Marker> childrenMarkers = new LinkedList<Marker>();
		if (children == null || children.isEmpty()) {
			childrenMarkers.add(markers.get(marker));
		} else {
			for (MarkerTypes markerType : children) {
				childrenMarkers.addAll(getAllLeafs(markerType));
			}
		}
		logger.exit(childrenMarkers);
		return childrenMarkers;
	}

	/**
	 * @return the roots
	 */
	public static MarkerTypes[] getRoots() {
		return roots;
	}

	public static Marker getMarker(MarkerTypes type) {
		return getMarkers().get(type);
	}

	public static String getName(MarkerTypes type) {
		return getMarkernames().get(type);
	}

	/**
	 * @return the markers
	 */
	public static Map<MarkerTypes, Marker> getMarkers() {
		return markers;
	}

	/**
	 * @return the markernames
	 */
	public static Map<MarkerTypes, String> getMarkernames() {
		return markerNames;
	}

	public static String getName(String name) {
		return getName(MarkerTypes.valueOf(name));
	}

	public static List<String> getAllMarkerOptions() {
		List<String> names = new LinkedList<String>();
		for (MarkerTypes root : roots) {
			putAllChildrenAsHtmlOption(root, names);
			names.add("<option data-divider=\"true\"></option>");
		}
		return names;
	}

	private static void putAllChildrenAsHtmlOption(MarkerTypes type, List<String> list) {
		Marker marker = getMarker(type);
		String label = CommonMethods.printMarker(marker);
		list.add("<option value=\"" + type + "\">" + label + "</option>");
		if (markerTree.containsKey(type)) {
			for (MarkerTypes child : markerTree.get(type)) {
				putAllChildrenAsHtmlOption(child, list);
			}
		}
	}
}
